package com.lmf.spring5.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


@Component
@Aspect         //spring自动生成代理对象，使用这个注解需要开启aspectj-autoproxy功能，基于xml的aop配置就可以不用开启
@Order(3)       //有多个增强类多同一个方法进行增强，设置增强类优先级；在增强类上面添加注解 @Order(数字类型值)，数字类型值越小优先级越高

//增强的类
public class UserProxy {
    //抽取公共的切入点
    @Pointcut(value = "execution(* com.lmf.spring5.aopanno.User.add(..))")
    public void pointDemo(){
    }

    /**
     * @Before：（1）一般在具体某个方法上面使用
     *      （2）使用在某个方法上面，就表示将该方法作为增强方法，会作用到execution表达式中的某个方法上面。且会在在那个方法前面执行
     *      （3）其他注解作用类似上面所述
     */
    //前置通知
//    @Before(value = "execution(* com.lmf.spring5.aopanno.User.add(..))")
    @Before(value = "pointDemo()")//使用公共切入点的方法
    public void beforeDemo(){
        System.out.println("原始方法之前执行：前置通知 before");
    }
    //后置通知（返回通知）(有异常，就不会执行)
    @AfterReturning(value = "execution(* com.lmf.spring5.aopanno.User.add(..))")
    public void afterReturningDemo() {
        System.out.println("原始方法执行完后执行：后置通知 afterReturning");
    }
    //最终通知(即使有异常，也会执行)
    @After(value = "execution(* com.lmf.spring5.aopanno.User.add(..))")
    public void afterDemo(){
        System.out.println("原始方法执行完后执行：最终通知 after");
    }
    //环绕通知
    @Around(value = "execution(* com.lmf.spring5.aopanno.User.add(..))")
    public void aroundDemo(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("原始方法之前执行：Around之前，比前置通知还要提前执行");
        proceedingJoinPoint.proceed();//执行原方法
        System.out.println("原始方法之前执行：Around之后，比前置通知还要提前执行");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.lmf.spring5.aopanno.User.add(..))")
    public void afterThrowingDemo(){
        System.out.println("无论前后：异常通知 afterThrowing");
    }
}
